package reit.ass3;

import java.util.Collection;
import java.util.Map;

import org.apache.log4j.Logger;

import com.google.common.collect.ArrayListMultimap;


/**
 * The Class Asset.
 */
class Asset implements LocatableInterface, NamableInterface,
Comparable<Asset>, StatusableInterface {
	/** The maximum health an asset can have. */
	public static final float MAX_HEALTH = 100;

	/** The name. */
	private final String fName; 

	/** The type. */
	private final String fType;

	/** The status. */
	private Status fStatus;

	/** The size. */
	private final int fSize;

	/** The cost per night. */
	private final int fCostPerNight;

	/** The health. */
	private float fHealth;

	/** The location. */
	private Location fLocation;

	/** The asset contents. */
	private ArrayListMultimap<String, AssetContent> fAssetContents;

	/** The logger. */
	private Logger fLogger;

	/**
	 * Instantiates a new asset.
	 *
	 * @param name the name
	 * @param type the type
	 * @param location the location
	 * @param size the size
	 * @param costPerNight the cost per night
	 * @param assetContentContainer the asset content container
	 */
	Asset(final String name, final String type, final Location location, final byte size,
			final byte costPerNight,
			final ArrayListMultimap<String, AssetContent> assetContentContainer) {
		fLogger = Logger.getLogger(Asset.class);
		this.fName = name;
		this.fType = type;
		this.fSize = size;
		this.fAssetContents = assetContentContainer;
		this.fCostPerNight = costPerNight;
		this.fLocation = location;
		this.fStatus = Status.AVAILABLE;
		this.fHealth = Asset.MAX_HEALTH;

	}

	/**
	 * Gets the size.
	 *
	 * @return the size
	 */
	public int getSize() {
		return fSize;
	}

	/**
	 * Gets the type.
	 *
	 * @return the type
	 */
	public String getType() {
		return fType;
	}

	/**
	 * Gets the status.
	 *
	 * @return the status
	 */
	public synchronized Status getStatus() {
		return fStatus;
	}

	/* (non-Javadoc)
	 * @see ass3.StatusableInterface#setStatusTo(ass3.Status)
	 */
	public synchronized void setStatusTo(final Status status) {
		this.fStatus = status;
		this.notifyAll();
	}

	/* (non-Javadoc)
	 * @see ass3.NamableInterface#getName()
	 */
	@Override
	public String getName() {
		return new String(this.fName);
	}

	/* (non-Javadoc)
	 * @see ass3.LocatableInterface#getLocation()
	 */
	@Override
	public Location getLocation() {
		return new Location(fLocation);
	}

	/* (non-Javadoc)
	 * @see ass3.LocatableInterface#getDistance(ass3.Location)
	 */
	@Override
	public Double getDistance(final Location loc) {
		return Locatable.getDistance(this.fLocation, loc);
	}

	/* (non-Javadoc)
	 * @see java.lang.Comparable#compareTo(java.lang.Object)
	 */
	@Override
	public int compareTo(final Asset o) {
		if (o instanceof Asset) {
			return this.fName.compareTo(((Asset) o).fName);
		} else {
			throw (new RuntimeException("trying to compare to non Asset"));
		}

	}

	/**
	 * Gets the cost per night.
	 *
	 * @return the mCostPerNight
	 */
	public int getCostPerNight() {
		return fCostPerNight;
	}

	/**
	 * Gets the asset contents.
	 *
	 * @return the mAssetContents
	 */
	public ArrayListMultimap<String, AssetContent> getAssetContents() {
		return fAssetContents;
	}

	/**
	 * Cause damage.
	 *
	 * @param damageToCause the damage to cause to asset
	 */
	public synchronized void causeDamage(final float damageToCause) {
		if (this.fHealth - damageToCause < 0) {
			this.fHealth = 0;
		} else {
			this.fHealth -= damageToCause;
		}
		Map<String, Collection<AssetContent>> assetContents = fAssetContents
				.asMap();
		for (String key : fAssetContents.keySet()) {
			Collection<AssetContent> assetContent = assetContents.get(key);
			for (AssetContent a : assetContent) {
				a.causeDamage(damageToCause);
			}
		}
		fLogger.info(MyStringBuilder.buildString("causing ",
				Float.toString(damageToCause), " damage to ", fName,
				" helath is now ", Float.toString(fHealth)));
	}

	/**
	 * Gets the health.
	 *
	 * @return the health
	 */
	public synchronized float getHealth() {
		return fHealth;
	}

}
